package com.pingao.mp.modular.fls.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pingao.mp.config.dict.DictConfig;
import com.pingao.mp.config.dict.DictItem;
import com.pingao.mp.modular.fls.entity.Activity;
import com.pingao.mp.modular.fls.entity.ActivityAwards;
import com.pingao.mp.modular.fls.entity.ActivityWinResult;
import com.pingao.mp.modular.fls.mapper.ActivityAwardsMapper;
import com.pingao.mp.modular.fls.mapper.ActivityMapper;
import com.pingao.mp.modular.fls.mapper.ActivityWinResultMapper;
import com.pingao.mp.modular.fls.service.ActivityService;
import com.pingao.mp.modular.sys.entity.User;
import com.pingao.mp.modular.sys.mapper.UserMapper;
import com.pingao.mp.utils.Constant;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;

import java.time.LocalDateTime;
import java.util.*;

import static org.apache.shiro.util.ThreadContext.getSubject;

/**
 * <p>
 * 活动 服务实现类
 * </p>
 *
 * @author 闻品高
 * @since 2020-01-15
 */
@Service
public class ActivityServiceImpl extends ServiceImpl<ActivityMapper, Activity> implements ActivityService {

    @Autowired
    private DataSourceTransactionManager dataSourceTransactionManager;
    @Autowired
    private TransactionDefinition transactionDefinition;

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private DictConfig dictConfig;
    @Autowired
    private ActivityAwardsMapper activityAwardsMapper;
    @Autowired
    private ActivityWinResultMapper activityWinResultMapper;

    @Override
    public Map<String, Object> getActivityList(Integer pageNumber, Integer pageSize, String searchText, String sortName, String sortOrder, Integer status) {
        Map<String, Object> map = new HashMap<>();
        Page<Activity> page = new Page<>(pageNumber, pageSize);
        QueryWrapper<Activity> wrapper = new QueryWrapper<>();
        wrapper.eq("1", "1");
        if (status != null) {
            wrapper.eq(Activity.COL_STATUS, status);
        }
        if (searchText != null && !"".equals(searchText)) {
            wrapper.and(q -> q.like(Activity.COL_NAME, searchText).or().like(Activity.COL_CONTENT, searchText).or().like(Activity.COL_PRECAUTIONS, searchText).or().like(Activity.COL_REMARK, searchText).or().like(Activity.COL_RULE, searchText));
        }

        switch (sortName) {
            case "addTime":
                sortName = Activity.COL_ADD_TIME;
                break;
            case "startingTime":
                sortName = Activity.COL_STARTING_TIME;
                break;
            case "endTime":
                sortName = Activity.COL_END_TIME;
                break;
        }

        if (sortOrder.equals("desc") || sortOrder.equals("DESC")) {
            wrapper.orderByDesc(sortName);
        } else {
            wrapper.orderByAsc(sortName);
        }
        baseMapper.selectPage(page, wrapper);
        List<Activity> list = page.getRecords();
        addOtherField(list);
        map.put("rows", list);
        map.put("total", page.getTotal());
        return map;
    }

    @Override
    public boolean saveActivity(Activity activity) {
        TransactionStatus transactionStatus = null;
        try {
            Subject u = getSubject();
            Session s = u.getSession();
            User user = (User) s.getAttribute(Constant.LoginUser);
            List<ActivityAwards> awards = JSON.parseArray(activity.getAwards(), ActivityAwards.class);
            transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
            activity.setAddTime(LocalDateTime.now());
            activity.setUserId(user.getId());
            activity.insertOrUpdate();
            for (ActivityAwards award : awards) {
                award.setActivityId(activity.getId());
                award.insertOrUpdate();
            }
            dataSourceTransactionManager.commit(transactionStatus);
            return true;
        } catch (Exception ex) {
            if (transactionStatus != null) dataSourceTransactionManager.rollback(transactionStatus);
            throw ex;
        }
    }

    @Override
    public boolean editActivity(Activity activity) throws Exception {
        Activity activity1 = baseMapper.selectById(activity.getId());
        if (activity1 == null) {
            throw new Exception("对象不存在或已被删除");
        }

        if (activity1.getStartingTime().isBefore(LocalDateTime.now())) {
            throw new Exception("该活动已经开始，不允许修改");
        }

        if (activityWinResultMapper.selectCount(new QueryWrapper<ActivityWinResult>().eq(ActivityWinResult.COL_ACTIVITY_ID, activity1.getId())) > 0) {
            throw new Exception("该活动已经有人参与，不允许修改");
        }
        TransactionStatus transactionStatus = null;
        try {
            List<ActivityAwards> awards = JSON.parseArray(activity.getAwards(), ActivityAwards.class);
            transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
            activityAwardsMapper.delete(new QueryWrapper<ActivityAwards>().eq(ActivityAwards.COL_ACTIVITY_ID, activity1.getId()));
            activity.setAddTime(activity1.getAddTime());
            activity.setUserId(activity1.getUserId());
            activity.updateById();
            for (ActivityAwards award : awards) {
                award.setActivityId(activity.getId());
                award.insertOrUpdate();
            }
            dataSourceTransactionManager.commit(transactionStatus);
            return true;
        } catch (Exception ex) {
            if (transactionStatus != null) dataSourceTransactionManager.rollback(transactionStatus);
            throw ex;
        }
    }

    @Override
    public boolean deleteActivity(List<Long> ids) throws Exception {
        if (activityWinResultMapper.selectCount(new QueryWrapper<ActivityWinResult>().in(ActivityWinResult.COL_ACTIVITY_ID, ids)) > 0) {
            throw new Exception("所勾选的活动已经有人参加，不允许删除，请检查后再试");
        }
        TransactionStatus transactionStatus = null;
        try {
            transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
            activityWinResultMapper.delete(new QueryWrapper<ActivityWinResult>().in(ActivityWinResult.COL_ACTIVITY_ID, ids));
            activityAwardsMapper.delete(new QueryWrapper<ActivityAwards>().in(ActivityAwards.COL_ACTIVITY_ID, ids));
            baseMapper.delete(new QueryWrapper<Activity>().in(Activity.COL_ID, ids));
            dataSourceTransactionManager.commit(transactionStatus);
            return true;
        } catch (Exception ex) {
            if (transactionStatus != null) dataSourceTransactionManager.rollback(transactionStatus);
            throw ex;
        }
    }

    private void addOtherField(List<Activity> list) {
        if (list.size() < 1) {
            return;
        }
        Set<Long> userIds = new HashSet<>();
        for (Activity activity : list) {
            if (activity.getUserId() != null && activity.getUserId() > 0) {
                userIds.add(activity.getUserId());
            }
        }

        List<User> users = new ArrayList<>();
        if (userIds.size() > 0) {
            users = userMapper.selectList(new QueryWrapper<User>().in(User.COL_ID, userIds).select(User.COL_ID, User.COL_NAME, User.COL_NICK));
        }

        for (Activity activity : list) {
            for (User user : users) {
                if (user.getId().equals(activity.getUserId())) {
                    activity.setUserName(user.getName() + "-" + user.getNick());
                    break;
                }
            }

            for (DictItem dictItem : dictConfig.getFlags()) {
                if (dictItem.getValue().equals(activity.getStatus())) {
                    activity.setStatusName(dictItem.getName());
                    break;
                }
            }
        }
    }
}
